-
Notifications
You must be signed in to change notification settings - Fork 66
Wire up external API for attaching external subnets #9781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
bnaecker
commented
Feb 3, 2026
- Plumb the existing app layer code to the new attach / detach sagas
- Add a bunch of integration tests confirming the new API behavior
- Closes Control plane support for attached subnets. #9453
- Add APIs to the sled agent for attaching and detaching either a single subnet on an instance, or setting / clearing the entire set for an instance. - Add list of attached subnets in the instance-creation request body, and fill that in from Nexus with the (currently-empty) set of attached subnets for the target instnace. - Plumb attachment requests all the way through the sled-agent internals to the new APIs in OPTE. - Add mapping of attached subnets per-instance to the simulated sled agent for testing. - Fixes #9702
- Adds a subnet attach and detach saga in Nexus, modeled after the existing floating IP attachment sagas. - Update the common code for sagas to include passing or removing the attached subnets to Dendrite and / or OPTE. This is to pick up those changes during the existing instance sagas, e.g. instance update. - Fixes #9685
|
Stacked on #9780 |
2867c38 to
8e62a71
Compare
- Plumb the existing app layer code to the new attach / detach sagas - Add a bunch of integration tests confirming the new API behavior - Closes #9453
fe3ec22 to
7f2f485
Compare
|
Ok, I've taken this for a spin on I installed the TUF repo from 7f2f485 using I then used a combination of the CLI and console to:
I then created a subnet pool and member: And an external subnet out of that: You can actually already use the CLI to do this with It shows up in the list of attached subnets for the instance now: The background task for this appears to be running, correctly propagating the subnet to Dendrite and OPTE: Next I'm going to see if we can actually transit packets through this thing. |
rcgoodfellow
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
mergeconflict
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woohoo!
| const INSTANCE_NAME: &str = "test-instance"; | ||
|
|
||
| #[nexus_test] | ||
| async fn test_instance_external_subnet_list_empty( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a little hard for me to tell, is this old test subsumed by the new cannot_detach_subnet_that_is_not_attached?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so. The test test_external_subnet_attach has a few calls to this list endpoint for individual instances, e.g., L321 and L341.
|
Last testing note, just to confirm that this actually works end-to-end. I spun up a new debian instance on Then I SSHd into the machine, and listened for pings while pinging from my dev laptop (which is on the VPN). From the laptop: On the VM: |
- Add tests ensuring we can attach subnets to running and stopped instances both. - Add test ensuring we can't delete subnet while it's attached - Cleanup, use max attached subnet const
|
Tested with two k3s nodes (Debian 13 Trixie), pods successfully getting real routable IPs from attached external subnets, communicating cross-node with no NAT and no overlay. Step 1: BGPCreated an address lot for Step 2: Subnet Pool & External SubnetsAdded two /26 members to the subnet pool from the BGP-announced range:
Created and attached external subnets:
Step 3: Transit IPsSet transit IPs on each instance's NIC matching their attached subnet:
No custom VPC router routes were needed. Step 4: CNI Configuration (each node)Installed standard CNI plugins and Whereabouts IPAM. Bridge CNI config on each node with Node 1 ( {
"cniVersion": "0.3.1",
"name": "oxide-pod-network",
"plugins": [
{
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": false,
"ipam": {
"type": "whereabouts",
"range": "172.20.35.0/26",
"gateway": "172.20.35.1",
"exclude": ["172.20.35.1/32"],
"routes": [
{ "dst": "0.0.0.0/0", "gw": "172.20.35.1" }
]
}
}
]
}Node 2 mirrors with Step 5: Host RoutesEach node needs a route to the other node's pod subnet via OPTE: Node 1: ResultsCross-node pod-to-pod ping: tcpdump on pod 2 confirms no NAT or overlay: |